# ------------------------------------------------------------------------------------
# Helper to use RobWorkSim from outside project
#
# ROBWORKSIM_LIBRARIES is filled with all available RobWork libraries ROBWORKSIM_INCLUDE_DIRS is
# filled with RobWorkSim and available 3rdparty headers ROBWORKSIM_LIBRARY_DIRS is filled with
# RobWorkSim components libraries  and 3rdparty libraries paths
#
# www.robwork.dk
# ------------------------------------------------------------------------------------

# ---[ Find RobWorkSim

if(ROBWORKSIM_FIND_QUIETLY)
    set(QUIET_ QUIET)
else(ROBWORKSIM_FIND_QUIETLY)
    set(QUIET_)
endif(ROBWORKSIM_FIND_QUIETLY)

# ############################################# MACROS
# ##################################################################################################

# macro for determining the best RobWork build type match
macro(GET_ROBWORKSIM_BUILD_TYPE CFG_ROOT RW_BUILD_TYPE)
    # defaults to release
    set(BTYPE_TMP release)
    if(CMAKE_BUILD_TYPE)
        string(TOLOWER ${CMAKE_BUILD_TYPE} BTYPE_TMP)
    else()
        set(BTYPE_TMP "none")
    endif()

    # first test if the correct cmake build type is installed
    if(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_${BTYPE_TMP}.cmake)
        set(${RW_BUILD_TYPE} ${BTYPE_TMP})
    else()

        # find best robwork build match
        if(${BTYPE_TMP} STREQUAL "release")
            # find release compatible robwork installation
            if(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkSim!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "minsizerel")
            if(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkSim!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "relwithdebinfo")
            if(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkSim!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "debug")
            if(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkSim!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "none")
            if(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_debuge.cmake)
                set(${RW_BUILD_TYPE} debug)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkSim!")
            endif()
        else()
            message(
                STATUS
                    "Does not recognize build type: ${CMAKE_BUILD_TYPE} choosing any existing RobWorkSim installation!"
            )
            if(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkSimBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWorkSim!")
            endif()

        endif()
        message(
            STATUS
                "warning: RobWork was not compiled with type:${BTYPE_TMP} using type:${${RW_BUILD_TYPE}} instead!"
        )
    endif()

endmacro()

macro(RWSIM_MESSAGE text)
    if(IS_INSTALL)
        message(STATUS ${text})
    endif()
endmacro()

# ##################################################################################################

set(RWSIMCFG_ROOT ${CMAKE_CURRENT_LIST_DIR})

# check if user specified a RobWorkSim_DIR
if(DEFINED RobWorkSim_DIR)
    if(EXISTS "${RobWorkSim_DIR}/src/RobWorkSimConfig.hpp")
        # Found RobWorkSim in a build tree of RobWork
        set(RWSIMCFG_ROOT "${RobWorkSim_DIR}/cmake")
        set(is_installed false)
    elseif(EXISTS "${RobWorkSim_DIR}/RobWorkConfig.cmake")
        # Found a RobWorkSim installation
        set(RWSIMCFG_ROOT "${RobWorkSim_DIR}")
        set(is_installed true)
    elseif(
        EXISTS
        "${RobWorkSim_DIR}/include/robworksim-${RobWorkSim_VERSION_MAJOR}.${RobWorkSim_VERSION_MINOR}/RobWorkSimConfig.hpp"
    )
        set(
            RWSIMCFG_ROOT
            "${RobWorkSim_DIR}/share/robworksim-${RobWorkSim_VERSION_MAJOR}.${RobWorkSim_VERSION_MINOR}/"
        )
        set(is_installed true)
    else()
        # found no RobWork installation ot build tree in RobWorkSim_DIR so we try extracting it from
        # RobWorkSimConfig.cmake location instead
    endif()
    get_filename_component(RWSIMCFG_ROOT ${RWSIMCFG_ROOT} ABSOLUTE)
endif()

# get the relavant build type
get_robworksim_build_type(${RWSIMCFG_ROOT} RWSIM_BUILD_TYPE)

if(NOT TARGET sdurwsim)
    include("${RWSIMCFG_ROOT}/RobWorkSimTargets.cmake")
endif()

# check whether RobWorkSimConfig.cmake is found into a RobWorkSim installation or in a build tree
if(EXISTS "${RWSIMCFG_ROOT}/../src/RobWorkSimConfig.hpp")
    # Found RobWorkConfig.cmake in a build tree of RobWork
    set(succmsg "RobWorkSim: Found a RobWorkSim build tree")
    set(RWSIM_ROOT "${RWSIMCFG_ROOT}/..")

    # RobWork and RobWorkStudio roots should then be obvious
    set(RW_ROOT ${RWSIM_ROOT}/../RobWork)
    set(RWS_ROOT ${RWSIM_ROOT}/../RobWorkStudio)

    set(RWSIM_INCLUDE_EXT "${RWSIM_ROOT}/ext")
    set(RWSIM_INCLUDE_SRC "${RWSIM_ROOT}/src/")
    set(RWSIM_LIBS "${RWSIM_ROOT}/libs/${RWSIM_BUILD_TYPE}/")
    set(IS_INSTALL FALSE)

else()
    set(succmsg "RobWorkSim: Found a RobWorkSim installation")
    set(IS_INSTALL TRUE)
    # Found a RobWork installation
    if(WIN32)
        # RobWorkConfig.cmake is installed to RWSIM_ROOT/cmake
        set(RWSIM_ROOT "${RWSIMCFG_ROOT}/..")
        set(RWSIM_INCLUDE_EXT "${RWSIM_ROOT}/ext")
        set(RWSIM_INCLUDE_SRC "${RWSIM_ROOT}/include")
        set(RWSIM_LIBS "${RWSIM_ROOT}/libs/${RWSIM_BUILD_TYPE}")
    else()
        # RobWorkSimConfig.cmake is installed to RWSIM_INTALL/share/sdurwsim-x.y

        set(RWSIM_ROOT "${RWSIMCFG_ROOT}")
        set(RWSIM_INSTALL "${RWSIMCFG_ROOT}/../../..")
        set(RWSIM_LIBS "${RWSIM_INSTALL}/lib")
        set(
            RWSIM_INCLUDE_SRC
            "${RWSIM_INSTALL}/include/robworksim-${RobWorkSim_VERSION_MAJOR}.${RobWorkSim_VERSION_MINOR}"
        )
        set(
            RWSIM_INCLUDE_EXT
            "${RWSIM_INSTALL}/share/robworksim-${RobWorkSim_VERSION_MAJOR}.${RobWorkSim_VERSION_MINOR}/ext"
        )
    endif()
endif()

# MESSAGE(STATUS "RWSIM_ROOT   : ${RWSIM_ROOT}") MESSAGE(STATUS "RWSIMCFG_ROOT: ${RWSIMCFG_ROOT}")

# ##################################################################################################
# now RWSIM_ROOT and RWSIMCFG_ROOT is set. Lets extract the stuff needed to run a project

# next get the build configuration of the requested built type
if(EXISTS ${RWSIMCFG_ROOT}/RobWorkSimBuildConfig_${RWSIM_BUILD_TYPE}.cmake)
    include(${RWSIMCFG_ROOT}/RobWorkSimBuildConfig_${RWSIM_BUILD_TYPE}.cmake)

    # setup path to custom find scripts
    set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${RWSIMCFG_ROOT}/Modules")

    if(NOT DEFINED RobWork_DIR AND NOT ${IS_INSTALL})
        set(RobWork_DIR ${RW_ROOT}/cmake)
    endif()
    if(NOT DEFINED RobWorkStudio_DIR AND NOT ${IS_INSTALL})
        set(RobWorkStudio_DIR ${RWS_ROOT}/cmake)
    endif()

    find_package(RobWork REQUIRED)
    find_package(RobWorkStudio REQUIRED)

    # test if Bullet exists
    option(RWSIM_USE_BULLET "Set to ON if Bullet should be use. you may need to set BULLET_ROOT"
           ${RWSIM_BUILD_WITH_BULLET})
    if(RWSIM_USE_BULLET)
        if(RWSIM_BUILD_WITH_BULLET)
            if(NOT BULLET_ROOT)
                set(BULLET_ROOT ${RWSIM_BUILD_WITH_BULLET_ROOT})
            endif()
            if(NOT BULLET_INCLUDE_DIR)
                set(BULLET_INCLUDE_DIR ${RWSIM_BUILD_WITH_BULLET_INCLUDE_DIR})
            endif()

            find_package(Bullet)
            if(BULLET_FOUND)
                set(RWSIM_BULLET_LIBRARY sdurwsim_bullet)
                # BULLET_LIBRARIES
                message(STATUS "RobWorkSim: Bullet enabled and found.")
            else()
                set(RWSIM_HAVE_BULLET FALSE)
                message(
                    SEND_ERROR
                        "RobWorkSim: Bullet enabled but not found. Please setup BULLET_ROOT."
                        ${RWSIM_USE_ODE}
                )
            endif()
        else()
            message(
                SEND_ERROR
                    "RobWorkSim: Bullet enabled but RobWorkSim was NOT build with Bullet support! Please recompile RobWorkSim"
            )
        endif()
    else()
        message(STATUS "RobWorkSim: Bullet disabled.")
    endif()

    # test if ODE exists
    option(RWSIM_USE_ODE "Set to ON if ODE should be use. you may need to set ODE_ROOT"
           ${RWSIM_BUILD_WITH_ODE})
    if(RWSIM_USE_ODE)
        if(RWSIM_BUILD_WITH_ODE)
            set(ODE_USE_DOUBLE ${RWSIM_BUILD_WITH_ODE_USE_DOUBLE})
            set(ODE_USE_DEBUG ${RWSIM_BUILD_WITH_ODE_USE_DEBUG})
            if(NOT ODE_DIR)
                set(ODE_DIR ${RWSIM_BUILD_WITH_ODE_DIR})
            endif()
            if(NOT ODE_INCLUDE_DIR)
                set(ODE_INCLUDE_DIR ${RWSIM_BUILD_WITH_ODE_INCLUDE_DIR})
            endif()
            find_package(ODE)
            if(ODE_FOUND)
                set(RWSIM_ODE_LIBRARY sdurwsim_ode)
                # ODE_LIBRARIES
                message(STATUS "RobWorkSim: ODE enabled and found. Using ${ODE_BUILD_WITH}")
            else()
                message(SEND_ERROR "RobWorkSim: ODE enabled but not found. Please setup ODE_ROOT.")
            endif()
        else()
            message(
                SEND_ERROR
                    "RobWorkSim: ODE enabled but RobWorkSim was NOT build with ODE support! Please recompile RobWorkSim"
            )
        endif()
    else()
        message(STATUS "RobWorkSim: ODE disabled.")
    endif()

    # test if TNTPhysics exists
    option(RWSIM_USE_TNTPHYSICS "Set to ON if TNTPhysics should be used."
           ${RWSIM_BUILD_WITH_TNTPHYSICS})
    if(RWSIM_USE_TNTPHYSICS)
        if(RWSIM_BUILD_WITH_TNTPHYSICS)
            set(RWSIM_TNTPHYSICS_LIBRARY sdurwsim_tnt)
        else()
            message(
                SEND_ERROR
                    "RobWorkSim: TNTPhysics enabled but RobWorkSim was NOT build with TNTPhysics support! Please recompile RobWorkSim"
            )
        endif()
    else()
        message(STATUS "RobWorkSim: TNTPhysics disabled.")
    endif()

    set(ROBWORKSIM_BUILD_PATH "${RWSIM_BUILD_WITH_RWSIM_ROOT}")
    set(ROBWORKSIM_INCLUDE_DIRS_TMP "${RWSIM_BUILD_WITH_INCLUDE_DIRS}" "${ROBWORK_INCLUDE_DIR}")
    set(ROBWORKSIM_LIBRARY_DIRS_TMP "${RWSIM_BUILD_WITH_LIBRARY_DIRS}")
    set(ROBWORKSIM_LIBRARIES_TMP "${RWSIM_BUILD_WITH_LIBRARIES}" "${RWSIM_BUILD_WITH_LIB_DEPEND}"
                                 "${ROBWORK_LIBRARIES}")

    # make sure that the library and include paths are pointing to the right locations
    string(
        REPLACE
            "${ROBWORKSIM_BUILD_PATH}/ext" "${RWSIM_INCLUDE_EXT}" ROBWORKSIM_INCLUDE_DIRS
            "${ROBWORKSIM_INCLUDE_DIRS_TMP}"
    )
    string(
        REPLACE
            "${ROBWORKSIM_BUILD_PATH}/src" "${RWSIM_INCLUDE_SRC}" ROBWORKSIM_INCLUDE_DIRS
            "${ROBWORKSIM_INCLUDE_DIRS}"
    )
    list(REMOVE_DUPLICATES ROBWORKSIM_INCLUDE_DIRS)

    string(
        REPLACE
            "${ROBWORKSIM_BUILD_PATH}/libs/${RWSIM_BUILD_TYPE}" "${RWSIM_LIBS}"
            ROBWORKSIM_LIBRARY_DIRS "${ROBWORKSIM_LIBRARY_DIRS_TMP}"
    )
    list(REMOVE_DUPLICATES ROBWORKSIM_LIBRARY_DIRS)

    string(
        REPLACE
            "${ROBWORKSIM_BUILD_PATH}/libs/${RWSIM_BUILD_TYPE}" "${RWSIM_LIBS}" ROBWORKSIM_LIBRARIES
            "${ROBWORKSIM_LIBRARIES_TMP}"
    )
    list(REMOVE_DUPLICATES ROBWORKSIM_LIBRARIES)

    set(ROBWORKSIM_LIBRARIES_TMP ${ROBWORKSIM_LIBRARIES})
    set(ROBWORKSIM_LIBRARIES)
    foreach(l ${ROBWORKSIM_LIBRARIES_TMP})
        unset(tmp CACHE)
        find_library(
            tmp ${l}
            PATHS ${RWSIM_LIBS}
            PATH_SUFFIXES ${RWSIM_BUILD_WITH_LIBRARY_SUBDIRS}
            NO_DEFAULT_PATH
        )
        if(tmp)
            list(APPEND ROBWORKSIM_LIBRARIES ${tmp})
        else()
            list(APPEND ROBWORKSIM_LIBRARIES ${l})
        endif()
    endforeach()

    include(FindPackageHandleStandardArgs)
    find_package_handle_standard_args(
        RobWorkSim
        DEFAULT_MSG
        RWSIM_ROOT
        ROBWORKSIM_LIBRARIES
        ROBWORKSIM_INCLUDE_DIRS
        ROBWORKSIM_LIBRARY_DIRS
    )
    mark_as_advanced(ROBWORKSIM_LIBRARIES ROBWORKSIM_INCLUDE_DIRS ROBWORKSIM_LIBRARY_DIRS)

else()
    set(ROBWORKSIM_FOUND NOTFOUND)
    message(
        STATUS
            "This build of RobWorkSim is not compiled in ${RWSIM_BUILD_TYPE} please specify another buildtype!"
    )
endif()

if(ROBWORKSIM_FOUND)
    set(ROBWORKSIM_VERSION ${RobWorkSim_FOUND_VERSION} CACHE STRING "RobWorkSim version")
endif(ROBWORKSIM_FOUND)
